// Authentication.c - this processes and creates authentication messages
// PE23 20021023 update algorithm
// the authentication frame body structure contains space for the first 3
// elements of each authentication frame (algorithm type, sequence # and status
// code). The following bits will have, if present, algorithm specific infor-
// mation (like a challenge sequence)

#include "os_common.h"

void ProduceChallengeText(PWB32_ADAPTER Adapter, UCHAR *pbChallengeText, USHORT index)
{
	ULONG	ltime;
	USHORT	i;

    ///NdisGetSystemUpTime(&ltime);
	OS_TIMER_GET_SYS_TIME( &ltime );
	for (i=0; i<16; i++)
	{
    	*(((ULONG *)pbChallengeText)+i)   = (ULONG)((ltime+0xd35a822e)>>i); // @@ pbChallengeText is 4n alignment
    	*(((ULONG *)pbChallengeText)+(31-i))   = (ULONG)(ltime>>i)+0x3f489d2c; // @@
	}
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("Produce challenge text\n"));
	DataDmp(pbChallengeText, 128, 0);
	#endif
	OS_MEMORY_COPY( psBSS(index)->auth_challengeText, pbChallengeText, 128 );
}

//===========================================================================
//  SendAuthenticationRequest --
//
//  Description:
//    Send the authentication frame to the peer STA with auth. transaction
//    sequence number = 1 (first frame) or 3 (third frame), depending on
//    the current auth. session.
//
//  Arguments:
//    Adapter       - The pointer to the Miniport Adapter Context
//    peerSTAAddress- The Address of the peer STA that is desired to authen-
//                    ticate with.
//    iMSindex      -
//    wAuthenType   - AUTH_OPEN_SYSTEM or AUTH_SHARED_KEY.
//    wAuthenSeqNum -
//    wStatus       -
//    ChallengeText - Challenge text element. (Must with the size of 2+128 octets)
//
//  Return Value:
//    -1            - Failed to send.
//     1            - Has sent to the Tx handler.
//============================================================================
CHAR SendAuthenticationRequest(PWB32_ADAPTER    Adapter,
                               USHORT           iMSindex,
                               USHORT           wAuthenType,
                               USHORT           wAuthenSeqNum,
                               USHORT           wStatus,
                               PUCHAR           ChallengeText)  // PD43 20021004 Added
{
	struct Management_Frame*            msgHeader;
	struct Authentication_Frame_Body*   msgBody;
    PUCHAR                              msg;
    USHORT                               frameBodyLen;


	//TODO: If use WPA, it should use OPEN authentication
	if (wAuthenType >= WPA_AUTH)
		wAuthenType = OPEN_AUTH;

    // Get the free data buffer
    //
	if ((msg = MLMEGetMMPDUBuffer(Adapter)) == NULL)
	{
        // No available data buffer now. Stop send the MMPDU.
		Adapter->sMlmeFrame.wNumTxMMPDUDiscarded++;
		//_asm{ int 3 };  //CYLiu debug
        	return -1;
    	}
	msgHeader = (struct Management_Frame*) &msg[0];

	// setup Frame-Header subfield
	// first setup the frame_control header
	msgHeader->frame_control.mac_frame_info = MAC_SUBTYPE_MNGMNT_AUTHENTICATION;
	msgHeader->frame_control.to_ds      = 0;    // TO_DS=0 for management/control Frame
	msgHeader->frame_control.from_ds    = 0;    // FROM_DS=0 for management/control Frame
	msgHeader->frame_control.more_frag  = 0;
	msgHeader->frame_control.retry	    = 0;
	msgHeader->frame_control.more_data  = 0;
    msgHeader->frame_control.order      = 0;    // Set by the MDS
    msgHeader->frame_control.pwr_mgt    = 0;    // PD43 Adapter->pMac80211Parameters.iPowerSaveMode;
    msgHeader->frame_control.WEP        = 0;
    msgHeader->duration                 = 0;    // Set by the MDS
	
	OS_MEMORY_COPY( msgHeader->DA, psBSS(iMSindex)->abPeerAddress, MAC_ADDR_LENGTH );
	OS_MEMORY_COPY( msgHeader->SA, Adapter->sLocalPara.ThisMacAddress, MAC_ADDR_LENGTH );
	OS_MEMORY_COPY( msgHeader->BSSID, psBSS(iMSindex)->abBssID, MAC_ADDR_LENGTH );

    // SW-MAC does not fill the sequence no, but may fill the fragment no in
    // the MDS.
    //msgHeader->Sequence_Control = 0x00b0; // need to implement this

	msgBody = (struct Authentication_Frame_Body*) &msg[sizeof(struct Management_Frame)];
	//20060926 add by anson's endian
	msgBody->algorithmNumber = cpu_to_le16(wAuthenType);
	msgBody->sequenceNumber  = cpu_to_le16(wAuthenSeqNum);  // PE23 20021023 Modified
	msgBody->statusCode      = cpu_to_le16(wStatus);        // status code doesn't matter

	frameBodyLen = sizeof(struct Management_Frame) + sizeof(struct Authentication_Frame_Body);

    if ((ChallengeText != NULL) && (wAuthenType == SHARE_AUTH))
    {
        // 3rd auth. frame for Shared-key authentication

        // PD43 20021127 Modified
        // DO NOT KILL THIS COMMENT PLEASE. Austin ???? Unsure.
        //
        // The T-Link 11US01 11Mbps USB Adapter (ATMEL chip) does not encrypt
        // the 3rd auth. frame.
        // The Buffallo AP (WLAR-L11-L) and PCI AP (GW-AP11T) do not accept
        // an encrypted 3rd auth. frame and accept unencrypted 3rd auth. frame
        // instead.  As a result, deleted the following statementf first: WEP=1.
        msgHeader->frame_control.WEP = 1;   // Ask the HW-MAC to encrypt this auth-request frame.
        OS_MEMORY_COPY( &msg[30], ChallengeText, 2 + 128 ); // offset=30=sizeof(Management_Frame)+sizeof(Authentication_Frame_Body)=24+6
        // msg[30] = ELEMENT_ID_CHALLENGE_TEXT; // PD43
        // msg[31] = 128;                       // PD43
        frameBodyLen = frameBodyLen + 130;   // Include the challenge Text element
	}
    // for IBSS Authen Procedure, PD43 20021127
    else if ((wAuthenType == SHARE_AUTH) && (wAuthenSeqNum == 2))
    {
        // Need to instruct the HW-MAC to append the challenge text

        // PD43 20021210 Added
        msg[30] = ELEMENT_ID_CHALLENGE_TEXT;
        msg[31] = 128;
		// S/W produce the challenge text
		ProduceChallengeText(Adapter, msg+32, iMSindex);
        //frameBodyLen = frameBodyLen + 2;     // Include element ID and length field
        frameBodyLen = frameBodyLen + 130;     // Include element ID and length field

        // now send this message out
		if (1 == MLMESendFrame(Adapter,
								(UCHAR *)&msg[0],
								frameBodyLen,
								FRAME_TYPE_802_11_MANAGEMENT_CHALLENGE))
            return 1;                           // Has sent to the Tx handler.
        else
		{
			//return MLME buffer
			MLMEfreeMMPDUBuffer(Adapter, msg);
            return -1;
		}
    }

    // now send this message out
	if (1 == MLMESendFrame(Adapter,
							(UCHAR *)&msg[0],
							frameBodyLen,
							FRAME_TYPE_802_11_MANAGEMENT))
        return 1;                           // Has sent to the Tx handler.
	else
	{
		//return MLME buffer
		MLMEfreeMMPDUBuffer(Adapter, msg);
		return -1;
	}
}



// IBSS seems need not send out Deauthentication, added for DUT test
//===========================================================================
//  SendDeauthentication --
//
//  Description:
//
//  Arguments:
//    Adapter       - The pointer to the Miniport Adapter Context
//
//  Return Value:
//============================================================================
CHAR SendDeauthentication(PWB32_ADAPTER Adapter,
                          USHORT iMSindex,
                          USHORT reasonCode)
{
	PUCHAR	msg;
	struct Management_Frame* msgHeader;
	struct Deauthentication_Frame_Body* msgBody;

	if ((msg=MLMEGetMMPDUBuffer(Adapter))==NULL)
	{
		Adapter->sMlmeFrame.wNumTxMMPDUDiscarded++;
		return -1;  // fail get free msg buffer
	}
	msgHeader = (struct Management_Frame *) &msg[0];

	// setup Frame-Header subfields
	msgHeader->frame_control.mac_frame_info = MAC_SUBTYPE_MNGMNT_DEAUTHENTICATION;
    msgHeader->frame_control.to_ds      = 0;    // ToDs = 0 for MMPDU
    msgHeader->frame_control.from_ds    = 0;    // FromDs = 0 for MMPDU
	msgHeader->frame_control.more_frag 	= 0;
	msgHeader->frame_control.retry		= 0;
	msgHeader->frame_control.more_data 	= 0;
	msgHeader->frame_control.order		= 0;
    msgHeader->frame_control.pwr_mgt    = 0;    // PD43 Adapter->pMac80211Parameters.iPowerSaveMode;
    msgHeader->frame_control.WEP        = 0;
    msgHeader->duration                 = 0;    // Set by the MDS.
	
	OS_MEMORY_COPY( msgHeader->DA, Adapter->asBSSDescriptElement[iMSindex].abPeerAddress, MAC_ADDR_LENGTH );
	OS_MEMORY_COPY( msgHeader->SA, Adapter->sLocalPara.ThisMacAddress, MAC_ADDR_LENGTH );
	OS_MEMORY_COPY( msgHeader->BSSID, psBSS(Adapter->sLocalPara.wConnectedSTAindex)->abBssID, MAC_ADDR_LENGTH );

	// FrameSequenceNumber is generated by HW-MAC

	msgBody = (struct Deauthentication_Frame_Body*) &msg[sizeof(struct Management_Frame)];
	msgBody->reasonCode = cpu_to_le16(reasonCode); //20060926 add by anson's endian

    // now send this message out
	if (1 == MLMESendFrame( Adapter,
					(UCHAR *)&msg[0],
					sizeof(struct Management_Frame) + sizeof(struct Deauthentication_Frame_Body),
					FRAME_TYPE_802_11_MANAGEMENT))
        return 1;                           // Has sent to the Tx handler.
	else
	{
		//return MLME buffer
		MLMEfreeMMPDUBuffer(Adapter, msg);
		return -1;
	}

}


